package com.cafuc.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadOperation {

    public static int a = 0;
    public static int b = 0;
    public final static Object loackA = new Object();
    public final static Object loackB = new Object();
    public void lock1() {
        synchronized (loackA) {
            a ++;
            synchronized (loackB) {
                b ++;
            }
        }
    }
    public void lock2() {
        synchronized (loackA) {
            a --;
            synchronized (loackB) {
                b --;
            }
        }
    }

    private final Lock lock = new ReentrantLock();
    public void lockMethod() throws InterruptedException {
        if (lock.tryLock(3, TimeUnit.SECONDS)) {
            // 能够获取锁
            lock.lock();
            try {
                a ++;
            } finally {
                lock.unlock();
            }
        } else {
            // 不能获取锁
            // do other thing
        }
    }

    public synchronized void add(){
        if(a > 10000){
            dec();
        }else{
            a ++;
        }
    }

    public synchronized void dec(){
        if(a < 0){
            add();
        }else{
            a --;
        }
    }

    public void threadTest() {
        System.out.println("==== 开启主线程 ====");

        // 方式一：继承 Thread
        MyThread myThread = new MyThread();
//        myThread.setDaemon(true);
        myThread.start();

        // 方式二：实现 Runnable
        MyRunnable myRunnable = new MyRunnable();
        new Thread(myRunnable).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("==== 匿名内部类开启 Runnable 线程 ====");
            }
        }).start();
        new Thread(() -> System.out.println("==== Lambda 开启 Runnable 线程 ====")).start();

        // 方式三：实现 Callable 接口
        MyCallable myCallable = new MyCallable();
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<String> future = executorService.submit(myCallable);
        try {
            System.out.println(future.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
        executorService.shutdown();
    }

    public void synchThreadTest() throws Exception {
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (this) {
                    a ++;
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                synchronized (this) {
                    a --;
                }
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();

        System.out.println(a);
    }

    public void fixedThreadPool() {
        ExecutorService es = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 5; i ++) {
            es.submit(new MyRunnable(i + ""));
        }
        es.shutdown();
    }

    public void atomicTest() {
        AtomicLong atomicLong = new AtomicLong(0);
        for(int i = 0; i < 5; i ++) {
            new Thread(() -> {
                System.out.println(atomicLong.incrementAndGet() + "--" + (a++));
            }).start();
        }
    }

    public static void main(String[] args) throws Exception {
        ThreadOperation to = new ThreadOperation();
//        to.threadTest();
//        for (int i = 0; i < 100; i++) {
//            to.synchThreadTest();
//        }
        to.atomicTest();
//        to.fixedThreadPool();
    }
}